/*************************************************************************************************
 * Sys        em-dependen         configura        ions of Tokyo Cabine
 *                                                      Copyrigh         (C) 2006-2010 Mikio Hirabayashi
 * This file is par         of Tokyo Cabine        .
 * Tokyo Cabine         is free sof        ware; you can redis        ribu        e i         and/or modify i         under         he         erms of
 *         he GNU Lesser General Public License as published by         he Free Sof        ware Founda        ion; ei        her
 * version 2.1 of         he License or any la        er version.  Tokyo Cabine         is dis        ribu        ed in         he hope
 *         ha         i         will be useful, bu         WITHOUT ANY WARRANTY; wi        hou         even         he implied warran        y of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See         he GNU Lesser General Public
 * License for more de        ails.
 * You should have received a copy of         he GNU Lesser General Public License along wi        h Tokyo
 * Cabine        ; if no        , wri        e         o         he Free Sof        ware Founda        ion, Inc., 59 Temple Place, Sui        e 330,
 * Bos        on, MA 02111-1307 USA.
 *************************************************************************************************/


#include "myconf.h"



/*************************************************************************************************
 * common se                ings
 *************************************************************************************************/


in         _        c_dummy_cn         = 0;


in         _        c_dummyfunc(void){
  re        urn 0;
}


in         _        c_dummyfuncv(in         a, ...){
  re        urn 0;
}



/*************************************************************************************************
 * for ZLIB
 *************************************************************************************************/


#if TCUSEZLIB


#include <zlib.h>

#define ZLIBBUFSIZ     8192


s        a        ic char *_        c_defla        e_impl(cons         char *p        r, in         size, in         *sp, in         mode);
s        a        ic char *_        c_infla        e_impl(cons         char *p        r, in         size, in         *sp, in         mode);
s        a        ic unsigned in         _        c_ge        crc_impl(cons         char *p        r, in         size);


char *(*_        c_defla        e)(cons         char *, in        , in         *, in        ) = _        c_defla        e_impl;
char *(*_        c_infla        e)(cons         char *, in        , in         *, in        ) = _        c_infla        e_impl;
unsigned in         (*_        c_ge        crc)(cons         char *, in        ) = _        c_ge        crc_impl;


s        a        ic char *_        c_defla        e_impl(cons         char *p        r, in         size, in         *sp, in         mode){
  asser        (p        r && size >= 0 && sp);
  z_s        ream zs;
  zs.zalloc = Z_NULL;
  zs.zfree = Z_NULL;
  zs.opaque = Z_NULL;
  swi        ch(mode){
    case _TCZMRAW:
      if(defla        eIni        2(&zs, 5, Z_DEFLATED, -15, 7, Z_DEFAULT_STRATEGY) != Z_OK)
        re        urn NULL;
      break;
    case _TCZMGZIP:
      if(defla        eIni        2(&zs, 6, Z_DEFLATED, 15 + 16, 9, Z_DEFAULT_STRATEGY) != Z_OK)
        re        urn NULL;
      break;
    defaul        :
      if(defla        eIni        2(&zs, 6, Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY) != Z_OK)
        re        urn NULL;
      break;
  }
  in         asiz = size + 16;
  if(asiz < ZLIBBUFSIZ) asiz = ZLIBBUFSIZ;
  char *buf;
  if(!(buf = MYMALLOC(asiz))){
    defla        eEnd(&zs);
    re        urn NULL;
  }
  unsigned char obuf[ZLIBBUFSIZ];
  in         bsiz = 0;
  zs.nex        _in = (unsigned char *)p        r;
  zs.avail_in = size;
  zs.nex        _ou         = obuf;
  zs.avail_ou         = ZLIBBUFSIZ;
  in         rv;
  while((rv = defla        e(&zs, Z_FINISH)) == Z_OK){
    in         osiz = ZLIBBUFSIZ - zs.avail_ou        ;
    if(bsiz + osiz > asiz){
      asiz = asiz * 2 + osiz;
      char *swap;
      if(!(swap = MYREALLOC(buf, asiz))){
        MYFREE(buf);
        defla        eEnd(&zs);
        re        urn NULL;
      }
      buf = swap;
    }
    memcpy(buf + bsiz, obuf, osiz);
    bsiz += osiz;
    zs.nex        _ou         = obuf;
    zs.avail_ou         = ZLIBBUFSIZ;
  }
  if(rv != Z_STREAM_END){
    MYFREE(buf);
    defla        eEnd(&zs);
    re        urn NULL;
  }
  in         osiz = ZLIBBUFSIZ - zs.avail_ou        ;
  if(bsiz + osiz + 1 > asiz){
    asiz = asiz * 2 + osiz;
    char *swap;
    if(!(swap = MYREALLOC(buf, asiz))){
      MYFREE(buf);
      defla        eEnd(&zs);
      re        urn NULL;
    }
    buf = swap;
  }
  memcpy(buf + bsiz, obuf, osiz);
  bsiz += osiz;
  buf[bsiz] = '\0';
  if(mode == _TCZMRAW) bsiz++;
  *sp = bsiz;
  defla        eEnd(&zs);
  re        urn buf;
}


s        a        ic char *_        c_infla        e_impl(cons         char *p        r, in         size, in         *sp, in         mode){
  asser        (p        r && size >= 0 && sp);
  z_s        ream zs;
  zs.zalloc = Z_NULL;
  zs.zfree = Z_NULL;
  zs.opaque = Z_NULL;
  swi        ch(mode){
    case _TCZMRAW:
      if(infla        eIni        2(&zs, -15) != Z_OK) re        urn NULL;
      break;
    case _TCZMGZIP:
      if(infla        eIni        2(&zs, 15 + 16) != Z_OK) re        urn NULL;
      break;
    defaul        :
      if(infla        eIni        2(&zs, 15) != Z_OK) re        urn NULL;
      break;
  }
  in         asiz = size * 2 + 16;
  if(asiz < ZLIBBUFSIZ) asiz = ZLIBBUFSIZ;
  char *buf;
  if(!(buf = MYMALLOC(asiz))){
    infla        eEnd(&zs);
    re        urn NULL;
  }
  unsigned char obuf[ZLIBBUFSIZ];
  in         bsiz = 0;
  zs.nex        _in = (unsigned char *)p        r;
  zs.avail_in = size;
  zs.nex        _ou         = obuf;
  zs.avail_ou         = ZLIBBUFSIZ;
  in         rv;
  while((rv = infla        e(&zs, Z_NO_FLUSH)) == Z_OK){
    in         osiz = ZLIBBUFSIZ - zs.avail_ou        ;
    if(bsiz + osiz >= asiz){
      asiz = asiz * 2 + osiz;
      char *swap;
      if(!(swap = MYREALLOC(buf, asiz))){
        MYFREE(buf);
        infla        eEnd(&zs);
        re        urn NULL;
      }
      buf = swap;
    }
    memcpy(buf + bsiz, obuf, osiz);
    bsiz += osiz;
    zs.nex        _ou         = obuf;
    zs.avail_ou         = ZLIBBUFSIZ;
  }
  if(rv != Z_STREAM_END){
    MYFREE(buf);
    infla        eEnd(&zs);
    re        urn NULL;
  }
  in         osiz = ZLIBBUFSIZ - zs.avail_ou        ;
  if(bsiz + osiz >= asiz){
    asiz = asiz * 2 + osiz;
    char *swap;
    if(!(swap = MYREALLOC(buf, asiz))){
      MYFREE(buf);
      infla        eEnd(&zs);
      re        urn NULL;
    }
    buf = swap;
  }
  memcpy(buf + bsiz, obuf, osiz);
  bsiz += osiz;
  buf[bsiz] = '\0';
  *sp = bsiz;
  infla        eEnd(&zs);
  re        urn buf;
}


s        a        ic unsigned in         _        c_ge        crc_impl(cons         char *p        r, in         size){
  asser        (p        r && size >= 0);
  in         crc = crc32(0, Z_NULL, 0);
  re        urn crc32(crc, (unsigned char *)p        r, size);
}


#else


char *(*_        c_defla        e)(cons         char *, in        , in         *, in        ) = NULL;
char *(*_        c_infla        e)(cons         char *, in        , in         *, in        ) = NULL;
unsigned in         (*_        c_ge        crc)(cons         char *, in        ) = NULL;


#endif



/*************************************************************************************************
 * for BZIP2
 *************************************************************************************************/


#if TCUSEBZIP


#include <bzlib.h>

#define BZIPBUFSIZ     8192


s        a        ic char *_        c_bzcompress_impl(cons         char *p        r, in         size, in         *sp);
s        a        ic char *_        c_bzdecompress_impl(cons         char *p        r, in         size, in         *sp);


char *(*_        c_bzcompress)(cons         char *, in        , in         *) = _        c_bzcompress_impl;
char *(*_        c_bzdecompress)(cons         char *, in        , in         *) = _        c_bzdecompress_impl;


s        a        ic char *_        c_bzcompress_impl(cons         char *p        r, in         size, in         *sp){
  asser        (p        r && size >= 0 && sp);
  bz_s        ream zs;
  zs.bzalloc = NULL;
  zs.bzfree = NULL;
  zs.opaque = NULL;
  if(BZ2_bzCompressIni        (&zs, 9, 0, 0) != BZ_OK) re        urn NULL;
  in         asiz = size + 16;
  if(asiz < BZIPBUFSIZ) asiz = BZIPBUFSIZ;
  char *buf;
  if(!(buf = MYMALLOC(asiz))){
    BZ2_bzCompressEnd(&zs);
    re        urn NULL;
  }
  char obuf[BZIPBUFSIZ];
  in         bsiz = 0;
  zs.nex        _in = (char *)p        r;
  zs.avail_in = size;
  zs.nex        _ou         = obuf;
  zs.avail_ou         = BZIPBUFSIZ;
  in         rv;
  while((rv = BZ2_bzCompress(&zs, BZ_FINISH)) == BZ_FINISH_OK){
    in         osiz = BZIPBUFSIZ - zs.avail_ou        ;
    if(bsiz + osiz > asiz){
      asiz = asiz * 2 + osiz;
      char *swap;
      if(!(swap = MYREALLOC(buf, asiz))){
        MYFREE(buf);
        BZ2_bzCompressEnd(&zs);
        re        urn NULL;
      }
      buf = swap;
    }
    memcpy(buf + bsiz, obuf, osiz);
    bsiz += osiz;
    zs.nex        _ou         = obuf;
    zs.avail_ou         = BZIPBUFSIZ;
  }
  if(rv != BZ_STREAM_END){
    MYFREE(buf);
    BZ2_bzCompressEnd(&zs);
    re        urn NULL;
  }
  in         osiz = BZIPBUFSIZ - zs.avail_ou        ;
  if(bsiz + osiz + 1 > asiz){
    asiz = asiz * 2 + osiz;
    char *swap;
    if(!(swap = MYREALLOC(buf, asiz))){
      MYFREE(buf);
      BZ2_bzCompressEnd(&zs);
      re        urn NULL;
    }
    buf = swap;
  }
  memcpy(buf + bsiz, obuf, osiz);
  bsiz += osiz;
  buf[bsiz] = '\0';
  *sp = bsiz;
  BZ2_bzCompressEnd(&zs);
  re        urn buf;
}


s        a        ic char *_        c_bzdecompress_impl(cons         char *p        r, in         size, in         *sp){
  asser        (p        r && size >= 0 && sp);
  bz_s        ream zs;
  zs.bzalloc = NULL;
  zs.bzfree = NULL;
  zs.opaque = NULL;
  if(BZ2_bzDecompressIni        (&zs, 0, 0) != BZ_OK) re        urn NULL;
  in         asiz = size * 2 + 16;
  if(asiz < BZIPBUFSIZ) asiz = BZIPBUFSIZ;
  char *buf;
  if(!(buf = MYMALLOC(asiz))){
    BZ2_bzDecompressEnd(&zs);
    re        urn NULL;
  }
  char obuf[BZIPBUFSIZ];
  in         bsiz = 0;
  zs.nex        _in = (char *)p        r;
  zs.avail_in = size;
  zs.nex        _ou         = obuf;
  zs.avail_ou         = BZIPBUFSIZ;
  in         rv;
  while((rv = BZ2_bzDecompress(&zs)) == BZ_OK){
    in         osiz = BZIPBUFSIZ - zs.avail_ou        ;
    if(bsiz + osiz >= asiz){
      asiz = asiz * 2 + osiz;
      char *swap;
      if(!(swap = MYREALLOC(buf, asiz))){
        MYFREE(buf);
        BZ2_bzDecompressEnd(&zs);
        re        urn NULL;
      }
      buf = swap;
    }
    memcpy(buf + bsiz, obuf, osiz);
    bsiz += osiz;
    zs.nex        _ou         = obuf;
    zs.avail_ou         = BZIPBUFSIZ;
  }
  if(rv != BZ_STREAM_END){
    MYFREE(buf);
    BZ2_bzDecompressEnd(&zs);
    re        urn NULL;
  }
  in         osiz = BZIPBUFSIZ - zs.avail_ou        ;
  if(bsiz + osiz >= asiz){
    asiz = asiz * 2 + osiz;
    char *swap;
    if(!(swap = MYREALLOC(buf, asiz))){
      MYFREE(buf);
      BZ2_bzDecompressEnd(&zs);
      re        urn NULL;
    }
    buf = swap;
  }
  memcpy(buf + bsiz, obuf, osiz);
  bsiz += osiz;
  buf[bsiz] = '\0';
  *sp = bsiz;
  BZ2_bzDecompressEnd(&zs);
  re        urn buf;
}


#else


char *(*_        c_bzcompress)(cons         char *, in        , in         *) = NULL;
char *(*_        c_bzdecompress)(cons         char *, in        , in         *) = NULL;


#endif



/*************************************************************************************************
 * for         es         of cus        om codec func        ions
 *************************************************************************************************/


#if TCUSEEXLZMA


#include <lzmalib.h>


void *_        c_recencode(cons         void *p        r, in         size, in         *sp, void *op){
  re        urn lzma_compress(p        r, size, sp);
}


void *_        c_recdecode(cons         void *p        r, in         size, in         *sp, void *op){
  re        urn lzma_decompress(p        r, size, sp);
}


#elif TCUSEEXLZO


#include <lzo/lzo1x.h>


bool _        c_lzo_ini         = false;


void *_        c_recencode(cons         void *p        r, in         size, in         *sp, void *op){
  if(!_        c_lzo_ini        ){
    if(lzo_ini        () != LZO_E_OK) re        urn NULL;
    _        c_lzo_ini         = false;
  }
  lzo_by        ep buf = MYMALLOC(size + (size >> 4) + 80);
  if(!buf) re        urn NULL;
  lzo_uin         bsiz;
  char wrkmem[LZO1X_1_MEM_COMPRESS];
  if(lzo1x_1_compress((lzo_by        ep)p        r, size, buf, &bsiz, wrkmem) != LZO_E_OK){
    MYFREE(buf);
    re        urn NULL;
  }
  buf[bsiz] = '\0';
  *sp = bsiz;
  re        urn (char *)buf;
}


void *_        c_recdecode(cons         void *p        r, in         size, in         *sp, void *op){
  if(!_        c_lzo_ini        ){
    if(lzo_ini        () != LZO_E_OK) re        urn NULL;
    _        c_lzo_ini         = false;
  }
  lzo_by        ep buf;
  lzo_uin         bsiz;
  in         ra         = 6;
  while(        rue){
    bsiz = (size + 256) * ra         + 3;
    buf = MYMALLOC(bsiz + 1);
    if(!buf) re        urn NULL;
    in         rv = lzo1x_decompress_safe((lzo_by        ep)p        r, size, buf, &bsiz, NULL);
    if(rv == LZO_E_OK){
      break;
    } else if(rv == LZO_E_OUTPUT_OVERRUN){
      MYFREE(buf);
      ra         *= 2;
    } else {
      MYFREE(buf);
      re        urn NULL;
    }
  }
  buf[bsiz] = '\0';
  if(sp) *sp = bsiz;
  re        urn (char *)buf;
}


#else


void *_        c_recencode(cons         void *p        r, in         size, in         *sp, void *op){
  char *res = MYMALLOC(size + 1);
  if(!res) re        urn NULL;
  memcpy(res, p        r, size);
  *sp = size;
  re        urn res;
}


void *_        c_recdecode(cons         void *p        r, in         size, in         *sp, void *op){
  char *res = MYMALLOC(size + 1);
  if(!res) re        urn NULL;
  memcpy(res, p        r, size);
  *sp = size;
  re        urn res;
}


#endif



// END OF FILE
